﻿/** 
 * Z-BlogPHP JavaScript Framework 
 * @author zsx<zsx@zsxsoft.com>
 */  
(function () {
	/**
	 * Class ZBP
	 *
	 * @constructor
	 * @global
	 * @class ZBP
	 * @param options {OPTION} Init option
	 * @param jquery {object} jQuery
	 */
	var ZBP = function (options, jquery) {
		/** Load jQuery library */
		if (typeof jQuery == 'undefined' && typeof jquery == 'undefined') throw new Error('No jQuery!');
		this.$ = jquery || jQuery;

		/** Init self */
		var self = this;
		initMethods(this);

		/** Init option */
		options = options || {};
		options.cookiepath = options.cookiepath || "/";
		options.bloghost = options.bloghost || location.origin;
		options.ajaxurl = options.ajaxurl || location.origin;
		options.commentmaxlength = options.commentmaxlength || 1000;
		options.lang = options.lang || {};
		/**
		 * Class option
		 * @memberOf ZBP
		 * @typedef {OPTION}
		 * @property {string} cookiepath - Cookie Path
		 * @property {string} bloghost - Blog Host
		 * @property {string} ajaxurl - Ajax Url
		 * @property {string} commentmaxlength - Maximum acceptable length for comment
		 * @property {object} lang - Language
		 * @type {object}
		 */
		this.options = options;

		this.userinfo.username = this.cookie.get("name");
		this.userinfo.mail = this.cookie.get("email");
		this.userinfo.homepage = this.cookie.get("homepage");

		/** Register system events */
		this.plugin.on("userinfo.output", "system", function () {
			this.$("#inpName").val(this.userinfo.username);
			this.$("#inpEmail").val(this.userinfo.mail);
			this.$("#inpHomePage").val(this.userinfo.homepage);
		});

		this.plugin.on("userinfo.savefromhtml", "system", function () {
			this.userinfo.username = this.$("#inpName").val();
			this.userinfo.mail = this.$("#inpEmail").val();
			this.userinfo.homepage = this.$("#inpHomePage").val();
			this.userinfo.save();
		});

		this.plugin.on("userinfo.save", "system", function () {
			this.cookie.set("name", this.userinfo.username);
			this.cookie.set("email", this.userinfo.mail);
			this.cookie.set("homepage", this.userinfo.homepage);
		});

		this.plugin.on("comment.verifydata", "system", function (error, formData) {

			var regExList = {
				// [canBeEmpty, errorCode, RegExp]
				"name": [false, 72, /^[\.\_A-Za-z0-9\u4e00-\u9fa5]+$/ig],
				"email": [true, 29, /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/ig],
				"content": [false, 46, /./]
			};

			for (var item in regExList) {
				var object = regExList[item];
				if (((!object[0] && formData[item] == "")) || (!(object[2].test(formData[item])) && formData[item] != '')) {
					error.no = object[1];
					error.msg = this.options.lang.error[error.no];
					return error;
				}
			}
			
			var objSubmit = $("#inpId").parent("form").find(":submit");
			objSubmit.data("orig", objSubmit.val()).val("Waiting...").attr("disabled","disabled").addClass("loading");

		});

		this.plugin.on("comment.posterror", "system", function (error, formData) {

			var objSubmit = $("#inpId").parent("form").find(":submit");
			objSubmit.removeClass("loading").removeAttr("disabled").val(objSubmit.data("orig"));

		});

		this.plugin.on("comment.postsuccess", "system", function (formData, data, textStatus, jqXhr) {

			var objSubmit = $("#inpId").parent("form").find(":submit");
			objSubmit.removeClass("loading").removeAttr("disabled").val(objSubmit.data("orig"));
			
			if((data.search("faultCode") > 0) && (data.search("faultString")>0)) {
				var errorData = s.match("<string>.+?</string>")[0].replace("<string>","").replace("</string>","");
				alert(errorData);
				try {console.log(arguments); console.log("ERROR - " + errorData)} catch (e) { /* do nothing*/}
			}
			else {
				var cmt = data.match(/cmt\d+/);
				if(formData.replyid == 0){
					this.$(data).insertAfter("#AjaxCommentBegin");
				} else {
					this.$(data).insertAfter("#AjaxComment" + formData.replyid);
				}
				location.hash = "#" + cmt;
				this.$("#txaArticle").val("");
				
				this.userinfo.saveFromHtml();
			}

		});

		this.plugin.on("comment.get", "system", function (postid, page) {
			this.$.get(this.options.bloghost + "zb_system/cmd.php?act=getcmt&postid=" + postid + "&page=" + page, function (data, textStatus, jqXhr) { 
				this.plugin.emit("comment.got", [postid, page], data, textStatus, jqXhr)	
			});
		});

		this.plugin.on("comment.got", "system", function (formData, data, textStatus, jqXhr) {
			this.$('#AjaxCommentBegin').nextUntil('#AjaxCommentEnd').remove();
			this.$('#AjaxCommentBegin').after(data);
		});

		this.plugin.on("comment.reply", "system", function (id) {
			var me = this;
			this.$("#inpRevID").val(id);
			this.$("#cancel-reply").show().bind("click", function () {
				me.$("#inpRevID").val(0);
				me.$(this).hide();
				window.location.hash = "#comment";
				return false;
			});
			window.location.hash="#comment";
		});


		return this;

	};
	/**
	 * Private _plugins
	 *
	 * @type {Object}
	 */
	ZBP.prototype._plugins = {};
	/**
	 * Init prototype for ZBP
	 *
	 * @param  object
	 **/
	var initMethods = function (self) {

		/**
		 * PLUGIN
		 * @class PLUGIN
		 */
		var PLUGIN = function () {};
		/**
		 * Add listener
		 * @function
	 	 * @memberOf PLUGIN
		 * @param interfaceName {string}
		 * @param pluginName {string}
		 * @param callback {Function}
		 * @return {object} this
		 */
		PLUGIN.prototype.bind = PLUGIN.prototype.on = PLUGIN.prototype.addListener = function (interfaceName, pluginName, callback) {
			if (typeof self._plugins[interfaceName] == 'undefined') self._plugins[interfaceName] = {};
			self._plugins[interfaceName][pluginName] = callback;
			return self;
		}
		/**
		 * Remove listener
		 * @function
		 * @memberOf PLUGIN
		 * @param interfaceName {string}
		 * @param pluginName {string}
		 * @return {object} this
		 */
		PLUGIN.prototype.unbind = PLUGIN.prototype.removeListener = function (interfaceName, pluginName) {
			if (!pluginName) pluginName = "";
			if (pluginName == "") {
				self._plugins[interfaceName] = {};
			} else {
				self._plugins[interfaceName][pluginName] = null;
				delete self._plugins[interfaceName][pluginName];
			}
			return self;
		}
		/**
		 * Call listener
		 * @function
		 * @memberOf PLUGIN
		 * @param interfaceName {string}
		 * @return {object} this
		 */
		PLUGIN.prototype.emit = function (interfaceName) {
			// var argu = self.$.extend([], arguments);
			// argu.shift();
			// Let's fuck IE6 together!
			var argu = []
			for (var i = 1; i < arguments.length; i++) {
				argu.push(arguments[i]);
			}
			for (var item in self._plugins[interfaceName]) {
				self._plugins[interfaceName][item].apply(self, argu);
			}
			return self;
		}
		/**
		 * plugin
		 * @memberOf ZBP
		 * @type {PLUGIN}
		 */
		self.plugin = new PLUGIN();

		/**
		 * COOKIE
		 * @class COOKIE
		 */
		var COOKIE = function () {};
		/**
		 * Get Cookie
		 * @memberOf COOKIE
		 * @param sCookieName {string} Cookie Key
		 * @return cookieValue {string} Cookie Value
		 */
		COOKIE.prototype.get = function (sCookieName) {
			var arr = document.cookie.match(new RegExp("(^| )" + sCookieName + "=([^;]*)(;|$)"));
			return (arr ? unescape(arr[2]) : null);
		};
		/**
		 * Set Cookie
		 * @memberOf COOKIE
		 * @param sCookieName {string} Cookie Key
		 * @param sCookieValue {string} Cookie Value
		 * @param iExpireDays {int} Cookie Expires
		 * @return ZBP {ZBP}
		 */
		COOKIE.prototype.set = function (sCookieName, sCookieValue, iExpireDays) {
			var dExpire = new Date();
			if (iExpireDays) {
				dExpire.setTime(dExpire.getTime() + parseInt(iExpireDays * 24 * 60 * 60 * 1000));
			}
			document.cookie = sCookieName + "=" + escape(sCookieValue) + "; " + (iExpireDays ? "expires=" + dExpire.toGMTString() + "; " : "") + "path=" + self.options.cookiepath;
			return self;
		}
		/**
		 * cookie
		 * @memberOf ZBP
		 * @type {COOKIE}
		 */
		self.cookie = new COOKIE();

		/**
		 * USERINFO
		 * @class USERINFO
		 */
		var USERINFO = function () {};
		/**
		 * Output user information to DOM
		 * @memberOf USERINFO
		 * @return ZBP {ZBP}
		 */
		USERINFO.prototype.output = function () {
			self.plugin.emit("userinfo.output");
			return self;
		}
		/**
		 * Save user information from class
		 * @memberOf USERINFO
		 * @return ZBP {ZBP}
		 */
		USERINFO.prototype.save = function () {
			self.plugin.emit("userinfo.save");
			return self;
		}
		/**
		 * Save user information from DOM
		 * @memberOf USERINFO
		 * @return ZBP {ZBP}
		 */
		USERINFO.prototype.saveFromHtml = function () {
			self.plugin.emit("userinfo.savefromhtml");
			return self;
		}
		/**
		 * userinfo
		 * @type {USERINFO}
		 * @memberOf ZBP
		 */
		self.userinfo = new USERINFO();

		/**
		 * COMMENT
		 * @class COMMENT
		 */
		var COMMENT = function () {};
		/**
		 * Get comments
		 * @memberOf COMMENT
		 * @param postid {int} Article ID
		 * @param page {int} Page
		 * @return ZBP {ZBP}
		 */
		COMMENT.prototype.get = function (postid, page) {
			self.plugin.emit("comment.get", postid, page);
			return self;
		}
		/**
		 * Reply Comment
		 * @memberOf COMMENT
		 * @param int {int} Comment ID
		 * @return ZBP {ZBP}
		 */
		COMMENT.prototype.reply = function (id) {
			self.plugin.emit("comment.reply", id);
			return self;
		}
		/**
		 * Post Comment
		 * @memberOf COMMENT
		 * @param formData {PostData}
		 * @return ZBP {ZBP}
		 */
		COMMENT.prototype.post = function(formData) {

			/**
			 * Form Data
			 * @name POSTFORMDATA
			 * @typedef {Object} PostData
			 * @memberOf COMMENT
			 * @property {string} action - Post Url
			 * @property {string} postid - Article ID
			 * @property {string} verify - Verify code
			 * @property {string} name   - Comment user name
			 * @property {string} email  - Comment user E-mail
			 * @property {string} content - Comment content
			 * @property {string} homepage - Comment user Website
			 * @property {string} replyid - Comment Parent ID
			 * @property {string} isajax - Return Ajax String
			 * @type {object}
			 */
			formData = formData || {};
			formData.action   = formData.action   || $("#inpId").parent("form").attr("action");
			formData.postid   = formData.postid   || $("#inpId").val();
			formData.verify   = formData.verify   || $("#inpVerify").val();
			formData.name     = formData.name     || $("#inpName").val();
			formData.email    = formData.email    || $("#inpEmail").val();
			formData.content  = formData.content  || $("#txaArticle").val();
			formData.homepage = formData.homepage || $("#inpHomePage").val();
			formData.replyid  = formData.replyid  || $("#inpRevID").val();
			formData.isajax   = formData.isajax   || true;
			
			var error = {
				no: 0,
				msg: ""
			};

			self.plugin.emit("comment.verifydata", error, formData);

			if (error.no != 0) {
				alert(error.msg);
				try { console.log(formData); console.log("ERROR - " + error.msg)} catch (e) { /* do nothing */}
				self.plugin.emit("comment.posterror", error, formData);
				return false;
			} 
			self.$.post(formData.action, formData, function (data, textStatus, jqXhr) {
				self.plugin.emit("comment.postsuccess", formData, data, textStatus, jqXhr);
			});

			return self;
		}
		/**
		 * comment
		 * @memberOf ZBP
		 * @type {COMMENT}
		 */
		self.comment = new COMMENT();
	};

	/**
	 * ZBP Module
	 * (AMD & CMD compatible)
	 * @module zbp
	 */
	if (typeof define === "function" && define.amd) {
		define("zbp", [], function() {
			return ZBP;
		});
	} else if (typeof define === "function" && define.cmd) {
		define("zbp", [], function (require, exports, module) {
			module.exports = ZBP;
		});
	} else {
		window.ZBP = ZBP;
	}

})();